#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'liugenxian'
__mtime__ = '2017/3/8'
"""
"""
功能一：爬取所有会员的帖子，并存为html文件。
1.获取cookie. 用document.cookie的方式，并把cookie字符串转换为dict. 这里有个问题没有解决，为什么用request包提供的方法，得到的cookie结果和document.cookie获取的结果不一样。
2.获取所有发布过帖子的会员号，并将会员号存入list.
3.依次获取会员的帖子内容，存为文件，用多线程方式实现，每个线程同时获取5个会员的页面。
  * 3.1获取页面内容是一个函数，线程之间如何不冲突？
  * 3.2为每个会员建立相应的文件夹，文件存放在对应的文件夹下。
  * 3.3若文件存在，则覆盖，因为每次爬取时，帖子的内容可能有更新。只需判断文件夹是否存在，文件夹存在直接存文件，文件夹不存在则创建。
"""

myCookieStr = r"o_cookie=2822650346; pgv_info=pgvReferrer=&ssid=s1621300561; tvfe_boss_uuid=303f54fad5b0ed1a; pgv_pvid=8430805614; uniqueuid=5b0ff44903734ca1ebfe7cd0fecb4c8a; ptcz=d4d12a7cbcfb184a6659f5cb7a650a931914d0d013ece87ff6ee62679bc85dc6; pt2gguin=o2822650346; uin=o2822650346; skey=@2QH6CxycP; qqUser=%7B%22uin%22%3A2822650346%2C%22nickName%22%3A%22%5Cu51ac%5Cu5929%5Cu7684%5Cu70b9%5Cu70b9%22%7D; security_cookiereport=1489038901; MANYOU_SESSIONID_bf895=27c1dd26b435653b66b9a1636cd90fc2; 314962432_2822650346_credit=%E5%8F%91%E8%A1%A8%E5%9B%9E%E5%A4%8D_1"

import os
import datetime
import re
import requests
from bs4 import BeautifulSoup

import logging
logging.basicConfig(level=logging.INFO)

def cookieStr_To_Dict(cookieStr):
    """
    将 document.cookie 获取的 cookie 字符串转换为字典形式 {cookie_name:cookie_value}
    :param: cookieStr
    :return: cookieDict
    """
    # 分割为新的列表，去掉'; '
    cookieStr = cookieStr.split('; ')
    # 定义正则式，将=两边分开，存为一个tuple
    name_value = re.compile(r'^(.*?)=(.*?)$')
    # 将每一个tuple的两个值转为key和value，存入dict, key为cookie的名字，value为cookie的值
    cookieDict = {}
    for item in cookieStr:
        cookieDict[name_value.match(item).groups()[0]] = name_value.match(item).groups()[1]

    return cookieDict

def get_members_number(nMember, myCookies):
    """
    获取有编号（发布过帖子）的成员的会员号，相应URL即 http://qgc.qq.com/314962432/t/555
    :param nMember: 会员数量
    :param myCookies: 我的cookie 字典形式
    :return: list of members_number
    """
    base_url = r'http://qgc.qq.com' + r'/314962432/t/'
    members_number = []
    for n in range(9, nMember):  # 会员帖子从9号开始，1-8号帖子预留为通知公共帖子
        member_url = base_url + str(n)
        response = requests.get(member_url, cookies=myCookies)
        if response.status_code == requests.codes.ok:
            members_number.append(n)
            # logging.info(members_number)

    return members_number


def get_pageUrls_of_aMember(idMember, myCookies):
    """
    获取一个会员的帖子的全部页面的 url list
    :param idMember: 成员的会员号，即页面地址id，我的是555
    :param myCookies: 我的cookies 字典形式
    :return url list:
    """
    base_url = r'http://qgc.qq.com'
    member_url = base_url + r'/314962432/t/' + str(idMember)
    response = requests.get(member_url, cookies=myCookies)

    # "html.parser" 是 Python标准库 的 HTML 解析器
    # 对获取到的页面内容(response.content)进行解析
    soup = BeautifulSoup(response.content, "html.parser")

    # 找到名为class="page"的<div>标记, 在<div>内迭代所有<a>标记
    # 每个<a>里的<href>标记，即是需要找到的所有网页链接
    # 或直接找到 class=c_tx 的 <a> tag
    # page_tag = soup.find_all(lambda tag: tag.name == 'div' and tag.get('class') == ['page'])
    a_tag = soup.find_all(lambda tag: tag.name == 'a' and tag.get('class') == ['c_tx'])
    # logging.info(a_tag)

    # urls 为会员的帖子的全部页面的链接列表
    urls = [member_url]

    for a in a_tag:
        url = base_url + a.get('href')
        urls.append(url)

    return urls


def get_pageContent_of_aMember(idMember, pageUrls, myCookies):
    """
    获取会员帖子全部页面的内容，并保存文件(先创建会员文件夹，再存放文件)
    :param idMember: 会员号
    :param pageUrls: 会员的帖子的全部页面的 url list, 函数get_pageUrls_of_aMember()的返回值
    :param myCookies: 我的cookie 字典形式
    """
    directory = 'member' + '[' + 'S' + str(idMember) + ']'
    # 如果目录不存在则创建，存在什么都不做
    if not os.path.exists(directory):
        os.makedirs(directory)

    nowtime = re.sub(r'[^0-9]','',str(datetime.datetime.now()))    # 文件加上当前时间，去掉了非数字的字符
    name = directory + '/' + '[' + 'S' + str(idMember) + ']' + '-page-'

    for index, urls in enumerate(pageUrls):
        response = requests.get(urls, cookies=myCookies)
        filename = name + str(index) + '-' + nowtime + '.html'
        with open(filename, 'wb') as fd:   #  'w' 如果文件存在，会先清空再写入，文件名加上当前时间后，不会重复了
            for chunk in response.iter_content(chunk_size=1024):
                fd.write(chunk)

def storePosts_allMember():
    """
    爬取所有会员的帖子，并存为html文件。
    :return:
    """
    myCookieDict = cookieStr_To_Dict(myCookieStr)
    members_numList = get_members_number(15, myCookieDict)
    for i, aMember in enumerate(members_numList):
        aMember_pageURLs = get_pageUrls_of_aMember(aMember, myCookieDict)
        get_pageContent_of_aMember(aMember, aMember_pageURLs, myCookieDict)

if __name__=='__main__':
    storePosts_allMember()